/*************************************************************************
	> File Name: monolith/core/memory_utils.cc
	> Author: dzhang
	> Mail: dong.zhang@ingenic.com 
	> Created Time: Thu 17 Dec 2020 11:14:52 AM CST
 ************************************************************************/

#include "monolith/core/memory_utils.h"
#include <iostream>
#include "monolith/core/macros.h"
CC_NAME_SPACE_BEGIN

//#define MNN_DEBUG_MEMORY
static inline void **alignPointer(void **ptr, size_t alignment) {
    return (void **)((intptr_t)((unsigned char *)ptr + alignment - 1) & -alignment);
}

extern "C" void *memory_alloc_align(size_t size, size_t alignment) {
    ML_ASSERT(size > 0);

#ifdef ML_DEBUG_MEMORY
    return malloc(size);
#else
    void **origin = (void **)malloc(size + sizeof(void *) + alignment);
    ML_ASSERT(origin != NULL);
    if (!origin) {
        return NULL;
    }

    void **aligned = alignPointer(origin + 1, alignment);
    aligned[-1]    = origin;
    return aligned;
#endif
}

extern "C" void *memory_calloc_align(size_t size, size_t alignment) {
    ML_ASSERT(size > 0);

#ifdef ML_DEBUG_MEMORY
    return calloc(size, 1);
#else
    void **origin = (void **)calloc(size + sizeof(void *) + alignment, 1);
    ML_ASSERT(origin != NULL)
    if (!origin) {
        return NULL;
    }
    void **aligned = alignPointer(origin + 1, alignment);
    aligned[-1]    = origin;
    return aligned;
#endif
}

extern "C" void memory_free_align(void *aligned) {
#ifdef ML_DEBUG_MEMORY
    free(aligned);
#else
    if (aligned) {
        void *origin = ((void **)aligned)[-1];
        free(origin);
    }
#endif
}

CC_NAME_SPACE_END
